// -------------------------------------------------
// BlinKit - BlinKit Library
// -------------------------------------------------
//   File Name: paint_session.cpp
// Description: PaintSession Class
//      Author: Ziming Li
//     Created: 2022-05-03
// -------------------------------------------------
// Copyright (C) 2022 MingYang Software Technology.
// -------------------------------------------------

#include "./paint_session.h"

#include <windowsx.h>
#include "blinkit/ui/animation/animation_frame.h"
#include "third_party/skia/include/core/SkCanvas.h"

namespace BlinKit {

PaintSession::PaintSession(Client &client) : m_client(client)
{
}

PaintSession::~PaintSession(void) = default;

void PaintSession::BitBlt(HDC hdc, int x, int y, int cx, int cy)
{
    auto _ = m_paintLock.guard();
    ::BitBlt(hdc, x, y, cx, cy, m_memoryDC, x, y, SRCCOPY);
}

SkColor PaintSession::DefaultBackgroundColor(void)
{
    COLORREF color = GetSysColor(COLOR_WINDOW);
    return SkColorSetARGB(0xff, GetRValue(color), GetGValue(color), GetBValue(color));
}

void PaintSession::FlushFrame(const SkBitmap &bitmap, const IntRect &dirtyRect, const SkPaint &paint)
{
    auto _ = m_paintLock.guard();

    SkCanvas canvas = m_currentFrame->BeginPaint();
    SkIRect src = SkIRect::MakeWH(dirtyRect.width(), dirtyRect.height());
    canvas.drawBitmapRect(bitmap, src, dirtyRect, &paint);

    m_client.BitBlt(m_memoryDC, dirtyRect);
}

void PaintSession::Initialize(HDC hdc, int cx, int cy)
{
    m_memoryDC = CreateCompatibleDC(hdc);

    cx = std::max(cx, 1);
    cy = std::max(cy, 1);
    m_currentFrame = std::make_unique<AnimationFrame>(IntSize(cx, cy));
    m_currentFrame->BeginPaint().clear(DefaultBackgroundColor());

    m_oldBitmap = SelectBitmap(m_memoryDC, *m_currentFrame);
}

void PaintSession::SwapFrame(std::unique_ptr<AnimationFrame> &frame, const IntSize &size)
{
    IntRect dirtyRect(IntPoint(), size);

    auto _ = m_paintLock.guard();

    m_currentFrame.swap(frame);
    SelectBitmap(m_memoryDC, *m_currentFrame);

    m_client.BitBlt(m_memoryDC, dirtyRect);
}

} // namespace BlinKit
